// --------------------------------------------------------------------------------------------------------------------
// <copyright file="FavouritesService.cs" company="XamlmNinja">
//   2010
// </copyright>
// <summary>
//   The favourites service.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace ServiceStyleRatherThanMessengerStyle.Services
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    using ServiceStyleRatherThanMessengerStyle.Model;

    using WP7Contrib.Collections;
    using WP7Contrib.Logging;
    using WP7Contrib.Services.Storage;

    /// <summary>
    /// The favourites service.
    /// </summary>
    public sealed class FavouritesService : IFavouritesService, IDisposable
    {
        #region Constants and Fields

        /// <summary>
        /// The storage key.
        /// </summary>
        private const string StorageKey = "favourites";

        /// <summary>
        /// The log.
        /// </summary>
        private readonly ILog log;

        /// <summary>
        /// The storage service.
        /// </summary>
        private readonly IStorageService storageService;

        /// <summary>
        /// The sync.
        /// </summary>
        private readonly object sync = new object();

        /// <summary>
        /// The favourites.
        /// </summary>
        private ObservableCollection<Person> favourites;

        /// <summary>
        /// The loaded.
        /// </summary>
        private bool loaded;

        /// <summary>
        /// The storage.
        /// </summary>
        private IStorage storage;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="FavouritesService"/> class.
        /// </summary>
        /// <param name="storageService">
        /// </param>
        /// <param name="log">
        /// </param>
        public FavouritesService(IStorageService storageService, ILog log)
        {
            this.storageService = storageService;
            this.log = log;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets Favourites.
        /// </summary>
        public ReadOnlyObservableCollection<Person> Favourites
        {
            get
            {
                if (!this.loaded)
                {
                    this.LoadFromStorage();
                }

                return new ReadOnlyObservableCollection<Person>(this.favourites);
            }
        }

        #endregion

        #region Implemented Interfaces

        #region IDisposable

        /// <summary>
        /// The dispose.
        /// </summary>
        public void Dispose()
        {
            if (this.storage != null)
            {
                this.storage.Dispose();
                this.storage = null;
            }
        }

        #endregion

        #region IFavouritesService

        /// <summary>
        /// Adds a property and the associated average houses prices.
        /// </summary>
        /// <param name="property">
        /// The currently selected property.
        /// </param>
        public void Add(Person property)
        {
            if (property == null)
            {
                return;
            }

            if (!this.loaded)
            {
                this.LoadFromStorage();
            }

            if (this.favourites.Contains(property))
            {
                return;
            }

            this.favourites.Add(property);
            this.storage.Write(StorageKey, this.favourites.ToList());
            this.storage.Flush();
        }

        /// <summary>
        /// The is a favourite.
        /// </summary>
        /// <param name="property">
        /// The property.
        /// </param>
        /// <returns>
        /// Returns true if the property is a favourite.
        /// </returns>
        public bool IsAFavourite(Person property)
        {
            if (property == null)
            {
                return false;
            }

            if (!this.loaded)
            {
                this.LoadFromStorage();
            }

            return this.favourites.Contains(property);
        }

        /// <summary>
        /// The remove favoutite.
        /// </summary>
        /// <param name="property">
        /// The property.
        /// </param>
        public void RemoveFavourite(Person property)
        {
            if (property == null)
            {
                return;
            }

            if (!this.loaded)
            {
                this.LoadFromStorage();
            }

            if (!this.favourites.Contains(property))
            {
                return;
            }

            this.favourites.Remove(property);
            this.storage.Write(StorageKey, this.favourites);
            this.storage.Flush();
        }

        #endregion

        #endregion

        #region Methods

        /// <summary>
        /// The load from storage.
        /// </summary>
        private void LoadFromStorage()
        {
            if (this.loaded)
            {
                return;
            }

            lock (this.sync)
            {
                if (this.loaded)
                {
                    return;
                }

                this.favourites = new ObservableCollection<Person>();
                this.storage = this.storageService.OpenPersistent(StorageKey);

                var favs = this.storage.Read<List<Person>>(StorageKey);
                if (favs == null || favs.Count == 0)
                {
                    this.log.Write("FavouritesService: No favourites");
                }
                else
                {
                    foreach (Person fav in favs)
                    {
                        this.log.Write("FavouritesService: Loading Property, hash code - " + fav.GetHashCode());
                        this.favourites.Add(fav);
                    }
                }

                this.loaded = true;
            }
        }

        #endregion
    }
}